package org.zjvis.datascience.web.shiro.config;

import java.util.Collection;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.AuthenticationStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zjvis.datascience.common.enums.LogEnum;


/**
 * @Description : Shiro 扩展父类原方法，捕获原始异常
 * @Date 2020-06-01
 */
public class ShiroModularRealmAuthenticator extends ModularRealmAuthenticator {
    private final static Logger logger = LoggerFactory.getLogger("ShiroModularRealmAuthenticator");
    /**
     * 扩展父类原方法，对异常立即进行外抛
     *
     * @param realms
     * @param token
     * @return
     */
    @Override
    protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms,
                                                            AuthenticationToken token) throws AuthenticationException {
        AuthenticationStrategy strategy = getAuthenticationStrategy();

        AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);
        AuthenticationException authenticationException = null;

        for (Realm realm : realms) {
            aggregate = strategy.beforeAttempt(realm, token, aggregate);

            if (realm.supports(token)) {

                AuthenticationInfo info = null;
                try {
                    info = realm.getAuthenticationInfo(token);
                } catch (AuthenticationException e) {
                    authenticationException = e;
                    logger.error("doMultiRealmAuthentication error :{} .", e);
                }

                aggregate = strategy.afterAttempt(realm, token, info, aggregate, authenticationException);

            } else {
                logger.info(String.format("Realm [%s] does not support token %s.  Skipping realm.", realm, token));
            }
        }
        //增加此逻辑，只有authenticationException不为null，则表示有Realm较验到了异常，
        if (authenticationException != null) {
            throw authenticationException;
        }
        aggregate = strategy.afterAllAttempts(token, aggregate);
        return aggregate;
    }

}

